package com.zelin.pay.service.impl;

import com.alibaba.dubbo.config.annotation.Service;
import com.alibaba.fastjson.JSON;
import com.alipay.api.AlipayApiException;
import com.alipay.api.internal.util.AlipaySignature;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zelin.dao.OrderDao;
import com.zelin.dao.PayLogDao;
import com.zelin.dao.SeckillGoodsDao;
import com.zelin.dao.SeckillOrderDao;
import com.zelin.entity.OrderEntity;
import com.zelin.entity.PayLogEntity;
import com.zelin.entity.SeckillGoodsEntity;
import com.zelin.entity.SeckillOrderEntity;
import com.zelin.entity.vo.PayAsyncVo;
import com.zelin.entity.vo.PayVo;
import com.zelin.pay.config.AlipayTemplate;
import com.zelin.pay.service.PayService;
import com.zelin.utils.MyDate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.Map;

/**
 * ------------------------------
 * 功能：
 * 作者：WF
 * 微信：hbxfwf13590332912
 * 创建时间：2021/8/17-15:05
 * ------------------------------
 */
@Service
public class PayServiceImpl extends ServiceImpl<PayLogDao, PayLogEntity>  implements PayService {

    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private AlipayTemplate alipayTemplate;
    @Autowired
    private OrderDao orderDao;
    @Autowired
    private SeckillOrderDao seckillOrderDao;
    @Autowired
    private SeckillGoodsDao goodsDao;
    //1. 从redis中查询出订单日志
    @Override
    public PayLogEntity findPayLogByUserId(String name) {
        String s = redisTemplate.opsForValue().get(name + ":paylog");
        PayLogEntity payLogEntity = JSON.parseObject(s, PayLogEntity.class);
        return payLogEntity;
    }

    //2. 从redis中根据订单号查询payVo对象(首先，得到支付日志，再得到payVo)
    @Override
    public PayVo findPayVoFromRedis(String name, String tradeNo) {
        //2.1 查询出支付日志对象
        String s = redisTemplate.opsForValue().get(name + ":paylog");
        //2.2 转换为payLog
        PayLogEntity payLogEntity = JSON.parseObject(s, PayLogEntity.class);
        //2.3 定义payVo对象
        PayVo payVo = new PayVo();
        payVo.setBody(payLogEntity.getBody());
        payVo.setOut_trade_no(payLogEntity.getOutTradeNo() + "");
        payVo.setSubject(payLogEntity.getSubject());
        payVo.setTotal_amount(payLogEntity.getTotalFee() + "");

        //2.4 返回
        return payVo;
    }

    /**
     * 功能: 返回的是支付的表单 页面
     * 参数:
     * 返回值: java.lang.String
     * @param payVo 支付参数
     * @param type 支付类型 1：支付宝支付 2：代表秒杀
     * 时间: 2021/8/17 15:26
     */
    @Override
    public String pay(PayVo payVo,int type) {
        try {
            return alipayTemplate.pay(payVo,type);
        } catch (AlipayApiException e) {
            e.printStackTrace();
        }
        return "hello";
    }

    /**
     * 功能: 验签并返回字符串，如果是success，就代表成功，否则，失败
     * 参数:
     * 返回值: java.lang.String
     * 时间: 2021/8/17 16:52
     */
    @Override
    public String payNotify(PayAsyncVo vo, Map<String, String> params) {
        try {
            //1. 进行验签
            boolean signVerified = AlipaySignature.rsaCheckV1(params, alipayTemplate.getAlipay_public_key(),
                    alipayTemplate.getCharset(), alipayTemplate.getSign_type()); //调用SDK验证签名

            //2. 判断是否验签成功
            if(signVerified){
                //第一部分：修改支付日志
                //2.1 更新支付日志与订单
                //String s = redisTemplate.opsForValue().get(userId + ":paylog");
                //PayLogEntity payLogEntity = JSON.parseObject(s, PayLogEntity.class);

                String out_trade_no = vo.getOut_trade_no();
                PayLogEntity payLogEntity = this.getById(out_trade_no);

                payLogEntity.setTransactionId(vo.getTrade_no());
                payLogEntity.setTradeState("1");        //代表己支付
                payLogEntity.setPayTime(new Date());    //设置支付时间
                //2.2 修改到数据库中
                this.updateById(payLogEntity);

                if (vo.getTrade_status().equals("TRADE_SUCCESS") || vo.getTrade_status().equals("TRADE_FINISHED")){
                    //第二部分：修改订单的状态
                    //2.1 得到订单id列表
                    String orderList = payLogEntity.getOrderList();
                    //2.2 使用,使用,号进行拆分
                    String[] split = orderList.split(",");
                    //2.3 遍历出每一个订单id
                    for (String orderId : split) {
                        //2.3.1 根据订单id查询出订单
                        OrderEntity orderEntity = orderDao.selectById(orderId);
                        //2.3.2 修改订单状态值
                        orderEntity.setStatus("2");     //2：代表己付款
                        //2.3.3 保存订单
                        orderDao.updateById(orderEntity);
                    }
                }

                System.out.println("支付成功");
                return "success";
            }
        } catch (AlipayApiException e) {
            e.printStackTrace();
        }
        System.out.println("支付失败！");
        return "fail";
    }

    /**
     * 功能: 代表秒杀的异步回调
     * 参数:
     * 返回值: java.lang.String
     * 时间: 2021/8/21 16:08
     */
    @Transactional
    @Override
    public String orderPayNotify(PayAsyncVo vo, Map<String, String> params) {
        try {
            //1. 进行验签
            boolean signVerified = AlipaySignature.rsaCheckV1(params, alipayTemplate.getAlipay_public_key(),
                    alipayTemplate.getCharset(), alipayTemplate.getSign_type()); //调用SDK验证签名

            //2. 判断是否验签成功
            if(signVerified){
                //第一部分：修改秒杀订单日志
                //1.1 得到秒杀订单号
                String out_trade_no = vo.getOut_trade_no();
                //1.2 根据订单号得到登录名
                String username = redisTemplate.opsForValue().get(out_trade_no);
                //1.3 根据登录名得到redis中的秒杀订单
                String secKillStr = (String) redisTemplate.boundHashOps("SeckillOrder").get(username);
                SeckillOrderEntity orderEntity = JSON.parseObject(secKillStr,SeckillOrderEntity.class);

                if (vo.getTrade_status().equals("TRADE_SUCCESS") || vo.getTrade_status().equals("TRADE_FINISHED")){
                    //第二部分：修改订单
                    //2.1 修改redis中的订单信息
                    orderEntity.setTransactionId(vo.getTrade_no()); //设置流水号
                    orderEntity.setPayTime(new Date());
                    orderEntity.setStatus("1");                     //代表支付成功
                    //2.2 保存到db中
                    seckillOrderDao.insert(orderEntity);            //添加到数据库中
                    //2.3 在db中将购买的商品的库存减掉
                    String time = MyDate.getDateStr(MyDate.getDateMenus().get(0));
                    String s = (String) redisTemplate.boundHashOps("SeckillGoods_" + time).get(orderEntity.getSeckillId() + "");
                    SeckillGoodsEntity seckillGoodsEntity = JSON.parseObject(s,SeckillGoodsEntity.class);
                    goodsDao.updateById(seckillGoodsEntity);

                    //2.4 从redis中删除订单
                    redisTemplate.boundHashOps("SeckillOrder").delete(username);
                    //2.5 也要删除该用户的排队相关的信息
                    //2.5.1 清除是否重复排队标识
                    redisTemplate.boundHashOps("UserQueueCount").delete(username);
                    //2.5.2 清除排队的标识信息
                    redisTemplate.boundHashOps("UserQueueStatus").delete(username);
                }

                System.out.println("支付成功");
                return "success";
            }
        } catch (AlipayApiException e) {
            e.printStackTrace();
        }
        System.out.println("支付失败！");
        return "fail";
    }
}
